import { defineComponent, onMounted, reactive, ref, nextTick, provide } from "vue";
import styles from "./index.module.less";
import ImportXml from "./ImportXml/ImportXml";
import AddChord from "./AddChord/AddChord";
import ImportMid from "./ImportMid/ImportMid";
import ResetLyrics from "./ResetLyrics/ResetLyrics";
import { useStore as useAnalysisStore } from "@/store/analysis";
import { useStore as useTagsStore } from "@/store/tags";
import { message, Modal } from "ant-design-vue";
import { $upload } from "@/apis/common/upload/upload";
import { $musicSongMelodyAnalysis, $musicSongDetail } from "@/apis/music/song/song";
import { $musicSongChords } from "@/apis/music/songChords/songChords";
import to from "await-to-js";
import { useRoute, useRouter } from "vue-router";
import eventBus from "@/common/eventBus/mitt";
import pako from "pako";
import uint8Array2Base64 from "@/common/utils/uint8Array2Base64";
import _ from "lodash";
import fetchBase64AsUint8Array from "@/common/utils/fetchBase64AsUint8Array";
import useDealMid from "@/common/hooks/dealMid";
import { getScoreToneChoose, getChooseScore } from "@/common/utils/getScoreToneChoose";
export default defineComponent({
  name: "MelodyAnalysis",
  setup() {
    const dealMidHook = useDealMid();
    const route = useRoute();
    const router = useRouter();
    const analysisStore = useAnalysisStore();
    const tagsStore = useTagsStore();
    const ResetrLyricsRef = ref(null as any);
    const modify = ref(false);
    const fetchData = reactive({
      lyricsData: null as any,
    });
    provide("fetchData", fetchData);
    const steps = reactive({
      list: [
        {
          title: '导入xml',
          content: () => <ImportXml />,
        },
        {
          title: '插入和弦',
          content: () => <AddChord />,
        },
        {
          title: '导入mid',
          content: () => <ImportMid />,
        },
        {
          title: '歌词排版',
          content: () => <ResetLyrics ref={ResetrLyricsRef} modify={modify.value} />,
        },
      ],
      current: -1,
    })
    const init = () => {
      steps.current = 0;
      analysisStore.init();
    }
    // 编辑状态处理mid文件
    const dealMid = async () => {
      if (!analysisStore.file?.mid) {
        message.error("请上传mid文件");
        return;
      }
      return await dealMidHook.dealFile(analysisStore.file.mid);
    }
    const nextStep = async () => {
      // 编辑时直接跳转到最后一步
      if (modify.value) {
        fetchData.lyricsData = null;
        steps.current = 3;
        return;
      }
      if (steps.current === 0) {
        if (!analysisStore.file.xml) {
          message.error("请上传xml文件!")
          return;
        }
        if (!analysisStore.tone.chord_tone) {
          message.error("请输入和弦调号!")
          return;
        }
        if (analysisStore.xmlData.measures.length === 0) {
          message.error("未获取到xml文件解析数据!")
          return;
        }
        const [musicSongChordsErr, musicSongChordsRes]: any = await to($musicSongChords());
        if (musicSongChordsErr) {
          message.error("和弦获取失败!");
          return;
        }
        const chords = musicSongChordsRes?.data?.data || [];
        let errs: string[] = [];
        // C#谱号转成Db,Cb谱号转成B
        if (analysisStore.tone.chord_tone === 'C#') {
          analysisStore.tone.chord_tone = "Db";
        } else if (analysisStore.tone.chord_tone === 'Cb') {
          analysisStore.tone.chord_tone = "B";
        }
        // C#谱号转成Db,Cb谱号转成B
        if (analysisStore.tone.score_tone === 'C#') {
          analysisStore.tone.score_tone = "Db";
        } else if (analysisStore.tone.score_tone === 'Cb') {
          analysisStore.tone.score_tone = "B";
        }
        analysisStore.xmlData.measures.forEach(x => {
          x.forEach(y => {
            if (y.chooseOri) {
              const choose: any = getScoreToneChoose(y.chooseOri, analysisStore.tone.chord_tone || 'C', chords);
              if (choose) {
                const chooseScore: any = getChooseScore(choose, analysisStore?.tone?.score_tone || "C", chords);
                if (chooseScore) {
                  y.choose = choose.name;
                  y.chooseScore = chooseScore;
                  y.chooseEnter = choose.enter;
                } else {
                  const err = `谱面和弦${y.chooseOri}未录入!`;
                  errs.includes(err) || errs.push(err);
                }
              } else {
                const err = `谱面和弦${y.chooseOri}未录入!`;
                errs.includes(err) || errs.push(err);
              }
            }
          })
        })
        if (errs?.length > 0) {
          Modal.confirm({
            title: "错误提示",
            content: <div>
              {
                errs.map(x => (
                  <div style={{ color: "red" }}>{x}</div>
                ))
              }
            </div>,
          })
          return;
        }
      }
      if (steps.current === 1) {
        analysisStore.setChordsData(_.cloneDeep(analysisStore.xmlData));
      }
      if (steps.current === 2) {
        if (!analysisStore.file.mid) {
          message.error("请上传mid文件!")
          return;
        }
        if (analysisStore.result.lyrics.length === 0) {
          message.error("未获取到mid文件解析数据!")
          return;
        }
      }
      steps.current++;
    }
    const prevStep = () => {
      if (modify.value) {
        steps.current = 1;
        return;
      }
      steps.current--;
    }
    const upload = async () => {
      const id = Number(route?.query?.id);
      const result = ResetrLyricsRef.value.getResult();
      if (result.lyrics.some(x => x.length > 15)) {
        message.error("单行歌词不得多于15字,请调整提示行!");
        return;
      }
      if (result.lyrics.some(x => x.some(y => y.errWord))) {
        Modal.confirm({
          title: "歌词错误",
          content: () => <span>歌词存在错字,请确认调整!</span>
        })
        return;
      }
      if (result.lyrics.some(x => x.some(y => y.repeatWord))) {
        const repeatWordConfirm = () => {
          return new Promise((resolve) => {
            Modal.confirm({
              title: "提示",
              content: () => <span>当前曲谱歌词存在自动查找匹配情况、请确认已完成歌词校对!</span>,
              onOk: () => {
                resolve(true);
              }
            })
          })
        }
        const repeatWordConfirmRes = await repeatWordConfirm();
        if (!repeatWordConfirmRes) {
          return;
        }
      }
      const scoreTone = analysisStore.tone.score_tone || "";
      const chordTone = analysisStore.tone.chord_tone || "";
      let xmlFileUrl = "";
      let midFileUrl = "";
      if (modify.value) {
        xmlFileUrl = analysisStore.file.xml;
        midFileUrl = analysisStore.file.mid;
      } else {
        const xmlFile = analysisStore.file.xml;
        const xmlFormData = new FormData();
        xmlFormData.append("file", xmlFile.originFileObj);
        const [xmlErr, xmlRes]: any = await to($upload(xmlFormData));
        if (xmlErr) {
          return;
        }
        xmlFileUrl = xmlRes.data?.data?.ossUpload?.fileUrl || "";
        const midFile = analysisStore.file.mid;
        const midFormData = new FormData();
        midFormData.append("file", midFile.originFileObj);
        const [midErr, midRes]: any = await to($upload(midFormData));
        if (midErr) {
          return;
        }
        midFileUrl = midRes.data?.data?.ossUpload?.fileUrl || "";
      }
      const chords = analysisStore.chordsData;
      const chordsDataStr = JSON.stringify(chords);
      let event = encodeURIComponent(chordsDataStr);
      let events_pako = pako.deflate(event);
      let chordsData: any = await uint8Array2Base64(events_pako);
      const resultStr = JSON.stringify(result);
      let event1 = encodeURIComponent(resultStr);
      let events_pako1 = pako.deflate(event1);
      let lyricsData: any = await uint8Array2Base64(events_pako1);

      const remarks = analysisStore.remarks;
      const remark = remarks?.map(x => x.name)?.join(",");

      const [err, res]: any = await to($musicSongMelodyAnalysis({
        id,
        scoreTone,
        chordTone,
        xmlFile: xmlFileUrl,
        midFile: midFileUrl,
        lyricsData,
        chordsData,
        remark,
      }))
      if (err) {
        return;
      }
      message.success("打谱成功!");
      init();
      eventBus.analysisFinish.emit();
      tagsStore.removeTagSimple(route.name);
      router.go(-1);
    }
    // 获取详情
    const getDetail = async () => {
      const id: string = String(route.query.id);
      const [err, res]: any = await to($musicSongDetail(id));
      if (!err) {
        try {
          const resultObj = res?.data?.data || null;
          analysisStore.file.xml = resultObj.xmlFile;
          analysisStore.file.mid = resultObj.midFile;
          let events_pako_return = "";
          const uint8Arr = await fetchBase64AsUint8Array(resultObj.chordsData);
          events_pako_return = new TextDecoder().decode(pako.inflate(uint8Arr));
          events_pako_return = decodeURIComponent(events_pako_return);
          const xmlData = JSON.parse(events_pako_return);
          let events_pako_return2 = "";
          const uint8Arr2 = await fetchBase64AsUint8Array(resultObj.lyricsData);
          events_pako_return2 = new TextDecoder().decode(pako.inflate(uint8Arr2));
          events_pako_return2 = decodeURIComponent(events_pako_return2);
          const xmlData2 = JSON.parse(events_pako_return2);
          fetchData.lyricsData = xmlData2;
          analysisStore.xmlData = xmlData;
          analysisStore.tone.score_tone = resultObj.scoreTone;
          analysisStore.tone.chord_tone = resultObj.chordTone;
          let remarks: any = [];
          if (resultObj.remark) {
            resultObj.remark?.split?.(",")?.forEach?.(x => {
              remarks.push({
                name: x,
                text: `和弦${x}暂未录入`
              })
            })
          }
          analysisStore.setRemarks(remarks)
        } catch { }
      }
      const res2 = await dealMid();
      if (!res2) {
        return;
      }
      analysisStore.result.temp = (fetchData.lyricsData?.temp && Number(fetchData.lyricsData?.temp) > 0) ? Number(fetchData.lyricsData?.temp) : 0;
      // 处理历史问题(和弦显示错误E# B#、升号显示改降号)
      if (analysisStore.xmlData.measures.some(x => x.some(y => !y.duration))) {
        message.error("曲谱数据异常请重新打谱!");
        return;
      }
      analysisStore.xmlData.measures.map(measure => measure.map(item => {
        if (item.chooseScore && item.chooseScore.includes("#")) {
          item.chooseScore = getChooseScore({ name: item.choose }, analysisStore?.tone?.score_tone || "C", []);
          return item;
        }
      }));
      analysisStore.setChordsData(_.cloneDeep(analysisStore.xmlData));
    }
    onMounted(async () => {
      analysisStore.init();
      if (route.query?.modify === '1') {
        await getDetail();
        modify.value = true;
        nextTick(() => {
          steps.current = 3;
        })
      } else {
        steps.current = 0;
      }
    })
    return () => (
      <div class={styles.page}>
        <div class={styles['wall-paper']}>
          <div class={styles["steps-diots"]}>
            <a-steps current={steps.current}>
              {
                steps.list.map(item => (
                  <a-step key={item.title} title={item.title} />
                ))
              }
            </a-steps>
          </div>
          <div class={styles['steps-content']}>
            {
              steps.list[steps.current]?.content?.()
            }
          </div>
          <div class={styles['steps-btn']}>
            {
              steps.current !== 0 && <a-button disabled={modify.value && steps.current === 1} onClick={() => { prevStep() }}>上一步</a-button>
            }
            {
              steps.current !== steps.list.length - 1 && <a-button type="primary" onClick={() => { nextStep() }}>下一步</a-button>
            }
            {
              steps.current === steps.list.length - 1 && <a-button type="primary" onClick={() => { upload() }}>上传</a-button>
            }
          </div>
        </div>
      </div>
    )
  }
})